package com.cuit.zuke.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.cuit.zuke.common.exception.GlobalException;
import com.cuit.zuke.common.util.Constant;
import com.cuit.zuke.common.util.PageUtil;
import com.cuit.zuke.system.dao.SysAdminDao;
import com.cuit.zuke.system.entity.SysAdminEntity;
import com.cuit.zuke.system.entity.SysMenuEntity;
import com.cuit.zuke.system.service.*;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @program: zuke
 * @description: AdminService实现类
 * @author: KamTang
 * @create: 2022-04-01 17:36
 **/
@Service
public class SysAdminServiceImpl extends ServiceImpl<SysAdminDao, SysAdminEntity> implements SysAdminService {

    @Autowired
    private SysDepartmentService departmentService;

    @Autowired
    private SysMenuService menuService;

    @Lazy
    @Autowired
    private SysAdminRoleService adminRoleService;

    @Lazy
    @Autowired
    private SysRoleService roleService;

    @Override
    public PageUtil queryPage(Map<String, Object> params) {
        String username = (String) params.get("username");
        String departmentIdStr = (String) params.get("departmentId");
        long currentPage = Long.parseLong((String) params.get("currentPage"));
        long pageSize = Long.parseLong((String) params.get("pageSize"));
        QueryWrapper<SysAdminEntity> wrapper = new QueryWrapper<>();
        wrapper.like(StringUtils.isNotBlank(username), "username", username);
        // departmentId无法使用wrapper内的表达式，因为在转换为long时，无法将 " " 转换
        // 将" "强制转换会报异常NumberFormatException   搜索条件为顶级部门id时，搜索全部。
        if (StringUtils.isNotBlank(departmentIdStr) && Long.parseLong(departmentIdStr) != 1L) {
            // 根据部门搜索时，部门id就是同一个
            long queryDepartmentId = Long.parseLong(departmentIdStr);
            wrapper.eq("department_id", queryDepartmentId);
        }

        Page<SysAdminEntity> entityPage = new Page<>(currentPage, pageSize);
        Page<SysAdminEntity> selectPage = this.baseMapper.selectPage(entityPage, wrapper);
        // 所有管理员
        List<SysAdminEntity> adminList = selectPage.getRecords();
        // 数据总条数
        int totalCount = (int) selectPage.getTotal();

        List<SysAdminEntity> collect =
                adminList.stream().peek(admin -> {
                    // 员工具体的所在部门取决于他的部门编号
                    long departmentId = admin.getDepartmentId();
                    // 这里调用了4次数据库
                    admin.setDepartment(departmentService.getById(departmentId).getName());
                    admin.setRoleIdList(adminRoleService.queryRoleIdList(admin.getUserId()));
                    admin.setRoles(roleService.getRoleInfoByUserId(admin.getUserId()));
                }).collect(Collectors.toList());

        return new PageUtil(collect, totalCount, (int) pageSize, (int) currentPage);
    }

    @Override
    public PageUtil queryAdmin(Map<String, Object> params) {
        int currentPage = Integer.parseInt((String) params.get("currentPage"));
        int pageSize = Integer.parseInt((String) params.get("pageSize"));
        params.put("currentPage", currentPage - 1);
        List<SysAdminEntity> adminList = this.baseMapper.queryAdmin(params);
        int size = adminList.size();
        return new PageUtil(adminList, size, currentPage, pageSize);
    }

    /**
     * 根据用户名，查询系统管理员
     *
     * @param username 用户名
     * @result AdminEntity
     */
    @Override
    public SysAdminEntity queryByUserName(String username) {
        return this.baseMapper.queryByUsername(username);
    }

    /**
     * 修改密码
     *
     * @param userId
     * @param password
     * @param newPassword
     */
    @Override
    public boolean updatePwd(Long userId, String password, String newPassword) {
        SysAdminEntity admin = new SysAdminEntity();
        admin.setPassword(newPassword);
        return this.update(admin, new QueryWrapper<SysAdminEntity>().eq("user_id", userId).eq("password", password));
    }

    /**
     * 根据部门id获取该部门下总人数
     *
     * @param departmentId
     * @return
     */
    @Override
    public int countPeopleByDepartmentId(Long departmentId) {
        QueryWrapper<SysAdminEntity> wrapper = new QueryWrapper<SysAdminEntity>().eq("department_id", departmentId);
        return this.baseMapper.selectCount(wrapper);
    }

    /**
     * 保存
     *
     * @param admin 管理员
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveUser(SysAdminEntity admin) {
        // 判断是否存在重名
        SysAdminEntity userName = queryByUserName(admin.getUsername());
        if (userName != null) {
            throw new GlobalException("该用户名已存在，请重新输入", 500);
        } else {
            // 256加密
            String salt = RandomStringUtils.randomAlphabetic(20);
            admin.setSalt(salt);
            admin.setPassword(new Sha256Hash(admin.getPassword(), salt).toHex());
            this.save(admin);
            //检查角色是否越权
            checkRole(admin);

            //保存用户与角色关系
            adminRoleService.saveOrUpdate(admin.getUserId(), admin.getRoleIdList());
        }
    }

    /**
     * 修改
     *
     * @param admin 管理员
     */
    @Override
    public void update(SysAdminEntity admin) {
        if (StringUtils.isBlank(admin.getPassword())) {
            admin.setPassword(null);
        } else {
            admin.setPassword(new Sha256Hash(admin.getPassword(), admin.getSalt()).toHex());
        }
        this.updateById(admin);

        //检查角色是否越权
        checkRole(admin);

        //保存用户与角色关系
        adminRoleService.saveOrUpdate(admin.getUserId(), admin.getRoleIdList());
    }

    /**
     * 根据id查询所有权限
     *
     * @param userId id
     * @return 改管理员的所有权限
     */
    @Override
    public List<String> queryAllPermsById(Long userId) {
        return this.baseMapper.queryAllPermsById(userId);
    }

    /**
     * 获取用户权限列表
     *
     * @param userId id
     * @return
     */
    @Override
    public Set<String> getUserPermissions(long userId) {
        List<String> permsList;
        if (userId == Constant.SUPER_ADMIN) {
            List<SysMenuEntity> menuList = menuService.getAllMenu();
            permsList = new ArrayList<>(menuList.size());
            for (SysMenuEntity menu : menuList
            ) {
                permsList.add(menu.getPerms());
            }
        } else {
            permsList = queryAllPermsById(userId);
        }
        //用户权限列表
        Set<String> permsSet = new HashSet<>();
        for (String perms : permsList) {
            // 去掉空值
            if (org.apache.commons.lang.StringUtils.isBlank(perms)) {
                continue;
            }
            permsSet.addAll(Arrays.asList(perms.trim().split(",")));
        }
        return permsSet;
    }

    /**
     * 根据用户id获取该用户的所有菜单id
     *
     * @param userId
     * @return
     */
    @Override
    public List<Long> getMenuIdByUserId(Long userId) {
        return this.baseMapper.getMenuIdByUserId(userId);
    }

    /**
     * 检查角色是否越权
     */
    private void checkRole(SysAdminEntity admin){
        if(admin.getRoleIdList() == null || admin.getRoleIdList().size() == 0){
            return;
        }
        //如果不是超级管理员，则需要判断用户的角色是否自己创建
        if(admin.getUserId() == Constant.SUPER_ADMIN){
            return ;
        }

        //查询用户创建的角色列表
        List<Long> roleIdList = roleService.queryRoleIdList(admin.getCreateUserId());

        //判断是否越权
        if(!roleIdList.containsAll(admin.getRoleIdList())){
            throw new GlobalException("新增用户所选角色，不是本人创建");
        }
    }
}
